// index.ts
import type { AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios'
import axios, { InternalAxiosRequestConfig } from 'axios'
import type { GetOptions, Result, TableInfo } from '@/types/Request'
import { SchemaTableType } from '@/types/Request'
import { ElMessage } from 'element-plus'
import {
  RootSchemaType,
} from '@/components/form-designer/setting-panel/data-source-setting/subscription-service/components/content/composables/useJsonSchemaToTree'


// 导出Request类，可以用来自定义传递配置来创建实例
export class Request {
  // axios 实例
  instance: AxiosInstance
  // 基础配置，url和超时时间
  baseConfig: AxiosRequestConfig = { baseURL: '/api', timeout: 60000 }

  constructor(config: AxiosRequestConfig) {
    // 使用axios.create创建axios实例
    this.instance = axios.create(Object.assign(this.baseConfig, config))

    this.instance.interceptors.request.use(
      (config: InternalAxiosRequestConfig) => {
        // 如果请求体中包含updateAt字段，删除它
        if (config?.data?.updateAt) {
          const { updateAt, createAt, ...rest } = config.data
          config.data = rest
        }
        return config
      },
      (err: any) => {
        // 请求错误，这里可以用全局提示框进行提示
        return Promise.reject(err)
      },
    )

    this.instance.interceptors.response.use(
      (res: AxiosResponse) => {
        // 直接返回res，当然你也可以只返回res.data
        // 系统如果有自定义code也可以在这里处理
        // console.log('interceptor response', res)
        if (res.data.code !== 200 && res.data.code !== 201) {
          return Promise.reject(res.data.message)
        }
        return res.data
      },
      (err: any) => {
        // 这里用来处理http常见错误，进行全局提示
        let message: string
        switch (err.response.status) {
          case 400:
            message = '请求错误(400)'
            break
          case 401:
            message = '未授权，请重新登录(401)'
            // 这里可以做清空storage并跳转到登录页的操作
            break
          case 403:
            message = '拒绝访问(403)'
            break
          case 404:
            message = '请求出错(404)'
            break
          case 408:
            message = '请求超时(408)'
            break
          case 500:
            message = '服务器错误(500)'
            break
          case 501:
            message = '服务未实现(501)'
            break
          case 502:
            message = '网络错误(502)'
            break
          case 503:
            message = '服务不可用(503)'
            break
          case 504:
            message = '网络超时(504)'
            break
          case 505:
            message = 'HTTP版本不受支持(505)'
            break
          default:
            message = `连接出错(${err.response.status})!`
        }
        // 这里错误消息可以使用全局弹框展示出来
        // 比如element plus 可以使用 ElMessage
        ElMessage({
          showClose: true,
          message: `${err.response?.data?.message || message}，请检查网络或联系管理员！`,
          type: 'error',
        })
        // 这里是AxiosError类型，所以一般我们只reject我们需要的响应即可
        console.error(err?.response?.data)
        // return Promise.reject(err.response)
      },
    )
  }

  public get<T = any>(url: string, options: GetOptions = {}): Promise<T extends TableInfo ? T : Result<T>> {
    return this.instance.get(url, options)
  }

  public post<T = any>(
    url: string,
    data?: any,
    config?: AxiosRequestConfig,
  ): Promise<Result<T>> {
    return this.instance.post(url, data, config)
  }

  public put<T = any>(
    url: string,
    data?: any,
    config?: AxiosRequestConfig,
  ): Promise<Result<T>> {
    return this.instance.put(url, data, config)
  }

  public delete(
    url: string,
    config?: AxiosRequestConfig,
  ): Promise<Result<boolean>> {
    return this.instance.delete(url, config)
  }
}

const { axios: api, ...otherProps } = window.$wujie?.props || {}


// 默认导出Request实例
export default {
  api,
  ...otherProps,
}

export function makePromiseResult<T>(data: T): Promise<Result<T>> {
  return Promise.resolve({
    code: 200,
    data,
    message: 'success',
  })
}

export function mockPromiseTable<T>(rows: T[]): Promise<TableInfo<T>> {
  return Promise.resolve({
    code: 200,
    rows,
    total: rows.length,
    message: 'success',
  })
}

export function mockPromiseSchemaTable<T>(schema: RootSchemaType, rows: T[]): Promise<SchemaTableType<T>> {
  return Promise.resolve({
    code: 200,
    schema,
    rows,
    total: rows.length,
    message: 'success',
  })
}
